package ch.zbw.sysventory.server.scanner;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

import org.springframework.stereotype.Component;

@Component
public class ComputerSocketCommunicator {
	private Socket socket;

	public Long getComputerId(String ipAddress, int port) throws Exception {
		String idString = this.sendMessage(ipAddress, port, "ComputerIdRequest");
		if (idString.indexOf(":") > 0) {
			idString = idString.substring(idString.indexOf(":") + 1);
			return Long.valueOf(idString);
		}
		return Long.valueOf(0);
	}

	public boolean sendNewComputerId(String ipAddress, int port, Long newComputerId) throws Exception {
		String response = this.sendMessage(ipAddress, port, "SetNewComputerIdRequest:" + newComputerId.longValue());
		if ("NewIdIsSet".equals(response))
			return true;
		return false;
	}

	public String getLatestScanResultXml(String ipAddress, int port) throws Exception {
		return this.sendMessage(ipAddress, port, "LatestScanResultRequest");
	}

	private String sendMessage(String ipAddress, int port, String message) throws Exception {
		this.openSocket(ipAddress, port);

		byte[] sendMessageBytes = message.getBytes();

		OutputStream out = socket.getOutputStream();
		DataOutputStream dos = new DataOutputStream(out);
		dos.writeLong(sendMessageBytes.length);
		dos.write(sendMessageBytes, 0, sendMessageBytes.length);
		dos.flush();

		InputStream in = socket.getInputStream();
		DataInputStream dis = new DataInputStream(in);
		long size = dis.readLong();
		byte[] buffer = new byte[1024];
		int bytesRead;
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		while (size > 0 && (bytesRead = in.read(buffer, 0, (int) Math.min(buffer.length, size))) != -1) {
			output.write(buffer, 0, bytesRead);
			size -= bytesRead;
		}
		String response = new String(output.toByteArray());
		in.close();
		this.closeSocket();
		return response;
	}

	private void openSocket(String ipAddress, int port) throws Exception {
		this.socket = new Socket(ipAddress, port);
	}

	private void closeSocket() throws Exception {
		this.socket.close();
	}
}
